package org.su.generalmvc.config;

import org.su.generalmvc.util.Assert;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.su.generalmvc.core.*;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * xssh包上下文，用于分析处理xssh.xml文件中的包内配置数据
 * 
 * @author yangchuan createtime:2012-4-20上午11:44:31
 * 
 */
public class PackageContext {

	/**
	 * 将所有拦截器存入临时上下文
	 */
	private Map<String, InterceptorStack> stackContext = new HashMap<String, InterceptorStack>();

	/**
	 * 将配置中的包存入临时环境
	 */
	private Map<String, PackageConfig> packageContext = new HashMap<String, PackageConfig>();

	/**
	 * 
	 */
	private IXsshApplicationContext context;

	protected static final Log logger = LogFactory.getLog(PackageContext.class);

	public void setContext(IXsshApplicationContext context) {
		this.context = context;
	}

	public void putStatck(String key, InterceptorStack is) {
		stackContext.put(key, is);
	}

	public void putPackage(String key, PackageConfig pc) {
		packageContext.put(key, pc);
	}

    /**
     * 分析并提取拦截栈里的拦截列表
     * @param pc
     * @param stackName
     * @param is
     */
	private void parseInterceptors(PackageConfig pc, String stackName,
			List<Interceptor> is) {
		String bn = pc.getName() + "." + stackName;
		Interceptor interceptor = (Interceptor) context.getBean(bn);
		if (interceptor == null) {
			InterceptorStack stack = stackContext.get(pc.getName() + "." + stackName);
			if (stack != null) {
				List<InterceptorRef> irs = stack.getInterceptorRef();
				if(irs!=null){
					for (InterceptorRef ir : irs) {
						parseInterceptors(pc, ir.getName(), is);
					}
				}
			} else {
				String parentName = pc.getExtend();
				if (StringUtils.isNotBlank(parentName)) {
					PackageConfig parent = packageContext.get(pc.getExtend());
					Assert.notNull(parent);
					parseInterceptors(parent, stackName, is);
				} else {
					throw new IllegalArgumentException(
							"[parse failed] - this interceptor-ref is not found a interceptor or interceptor-stack; it is name is:"
									+ stackName);
				}
			}
		} else {
			logger.debug("load interceptor in " + bn);
			is.add(interceptor);
		}
	}

	/**
	 * 清理上下文环境，及时释放数据
	 */
	private void clear() {
		stackContext.clear();
		packageContext.clear();
		context = null;
	}

	/**
	 * 解析包配置
	 * 
	 * @param roleInPackages
	 *            作用于控制器包的 ‘配置包’集合
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public void parseConfig(Map<String, XsshPackage> roleInPackages)
			throws SecurityException, NoSuchMethodException {
		parsePackage(roleInPackages);
		clear();
	}

	/**
	 * 解析包配置
	 * 
	 * @param _packages
	 *            作用于控制器包的 ‘配置包’集合
	 * @throws NoSuchMethodException
	 */
	private void parsePackage(Map<String, XsshPackage> _packages)
			throws NoSuchMethodException {
		List<PackageConfig> pcs = context.getConfig().getPackages();
		for (PackageConfig pc : pcs) {
			String name = pc.getName();
			XsshPackage xpc = new XsshPackage();

			if (StringUtils.isNotBlank(pc.getExtend())) {
				extendsParent(pc, xpc);
			}

			if (pc.getNamespace() != null) {
				xpc.setNamespace(pc.getNamespace());
				xpc.setViewdir(pc.getNamespace());
			}

			if (pc.getViewdir() != null) {
				xpc.setViewdir(pc.getViewdir());
			}

			if (StringUtils.isNotBlank(pc.getActionSuffix())) {
				xpc.setActionSuffix(pc.getActionSuffix());
			}

			if (StringUtils.isNotBlank(pc.getRoleIn())) {
				xpc.setRoleIn(pc.getRoleIn());
				_packages.put(pc.getRoleIn(), xpc);
			}

			putPackage(pc.getName(), pc);
			if (pc.getInterceptors() != null) {

				if (pc.getInterceptors() != null) {
					List<InterceptorStack> isSet = pc.getInterceptors()
							.getInterceptorStack();
					if (isSet != null) {
						for (InterceptorStack statck : isSet) {
							putStatck(pc.getName() + "." + statck.getName(),
									statck);
						}
					}
				}

				parseInterceptor(pc);
				InterceptorRef defaultRef = pc.getInterceptors()
						.getDefaultInterRef();
				if (defaultRef != null) {
					String defName = defaultRef.getName();
					Assert.notBlank(defName);
					List<Interceptor> is = new ArrayList<Interceptor>();
					logger.debug("loading Interceptor for " + pc.getName()
							+ " via interceptor-ref :" + defName);
					parseInterceptors(pc, defName, is);
					if (is.size() > 0 || StringUtils.isBlank(pc.getExtend())) {
						xpc.setInterceptorStack(is);
					}
				}
			}
			context.addPackage(name, xpc);

		}
	}

	/**
	 * 解析拦截器bean
	 * 
	 * @param pc
	 *            配置中的包对象
	 * @throws NoSuchMethodException
	 */
	private void parseInterceptor(PackageConfig pc)
			throws NoSuchMethodException {
		List<BeanMapping> ibs = pc.getInterceptors().getInterceptors();
		if(ibs == null) return ;
		for (BeanMapping ib : ibs) {
			String beanName = pc.getName() + "." + ib.getName();
			Assert.isFalse(context.containsBean(beanName));
			Interceptor interceptor = (Interceptor) context.addBean(beanName,
					ib.getClazz());
			LifeCycle lifeCycle = new LifeCycle(interceptor);
			Method initMethod = interceptor.getClass().getMethod("init");
			Method destroyMethod = interceptor.getClass().getMethod("destroy");
			lifeCycle.setInitMethod(initMethod);
			lifeCycle.setDestroyMethod(destroyMethod);
			LifeCycleManager.getInstence().add(lifeCycle);
			logger.info("found interceptor: " + ib.getClazz() + "");
		}
	}

	/**
	 * 继承父亲配置属性
	 * 
	 * @param pc
	 *            配置中的包对象
	 * @param xpc
	 *            解析后程序使用的包对象
	 */
	private void extendsParent(PackageConfig pc, XsshPackage xpc) {
		XsshPackage parentPackage = context.getPackage(pc.getExtend());
		xpc.setInterceptorStack(parentPackage.getInterceptorStack());
		xpc.setNamespace(parentPackage.getNamespace());
		xpc.setViewdir(parentPackage.getViewdir());
		xpc.setActionSuffix(parentPackage.getActionSuffix());
		xpc.setRoleIn(parentPackage.getActionSuffix());
	}

}
